<?php

namespace common\logics\trade;

use Yii;
use yii\db\Exception;
use common\models\trade\Trade;

/**
 * 交易操作相关逻辑模型
 * @author emhome
 * @since 2.0
 */
class TradeHandlerLogic extends Trade {

    /**
     * 取消过期交易
     * @param int $id 交易ID
     * @outputBuffering $msg
     * @return boolean
     */
    public static function cancelExpired($id, &$msg) {
        $trade = static::findOne($id);
        if ($trade == null) {
            $msg = '待操作的交易不存在！';
            return true;
        }
        if ($trade->expire_time > time()) {
            $msg = '当前交易还未过期！';
            return true;
        }
        if ($trade->status !== self::STATUS_DEFAULT && $trade->status !== self::STATUS_WAITPAY) {
            $msg = '当前交易状态已变更，禁止执行过期交易取消操作！';
            return true;
        }
        return static::cancelByTrade($trade, $msg, '交易过期');
    }

    /**
     * 关闭所有当前外部订单号的历史交易
     * @param string $bizno
     * @outputBuffering $msg
     * @return boolean
     */
    public static function closeByBizno($bizno, &$msg) {
        $trades = static::find()
        ->where(['bizno' => $bizno])
        ->andWhere([
            'status' => [
                static::STATUS_DEFAULT,
                static::STATUS_WAITPAY
            ]
        ])
        ->all();
        if (empty($trades)) {
            $msg = '未找到您要关闭的交易信息！';
            return false;
        }
        foreach ($trades as $trade) {
            if ($trade->status !== self::STATUS_DEFAULT && $trade->status !== self::STATUS_WAITPAY) {
                $msg = '当前交易状态已变更，禁止执行关闭交易的操作！';
                return false;
            }
            $status = static::cancelByTrade($trade, $msg, '交易关闭');
            if (!$status) {
                return false;
            }
        }
        return true;
    }

    /**
     * 取消所有当前外部订单号的历史交易
     * @param string $bizno
     * @outputBuffering $msg
     * @return boolean|static
     */
    public static function cancelByBizno($bizno, &$msg) {
        $trades = static::find()->andWhere([
            'bizno' => $bizno,
            'status' => [
                static::STATUS_DEFAULT,
                static::STATUS_WAITPAY
            ]
        ])->all();
        if (empty($trades)) {
            return true;
        }
        foreach ($trades as $trade) {
            if ($trade->status !== self::STATUS_DEFAULT && $trade->status !== self::STATUS_WAITPAY) {
                $msg = '当前交易状态已变更，禁止执行交易自动取消操作！';
                continue;
            }
//            if ($trade->expire_time > time() + 60) {
//                $msg = '当前交易还未过期！';
//                return $trade;
//            }
            $status = static::cancelByTrade($trade, $msg, '待产生新交易');
            if (!$status) {
                return false;
            }
        }
        return true;
    }

    /**
     * 取消交易
     * @param \common\trade\Trade $trade
     * @outputBuffering $msg
     * @param string|Unkown $prefixMessage
     * @return boolean
     */
    protected static function cancelByTrade($trade, &$msg, $prefixMessage = 'Unkown') {
        $refundOrders = [];
        //未付款或者待支付并且订单已过期则取消当前交易等操作
        $tradeAmount = $trade->getOrders()->sum('pay*balance*status');
        if ($tradeAmount > 0 && !empty($trade->paymentOrder)) {
            //查询当前交易中存在的已支付的交易订单
            foreach ($trade->paymentOrder as $order) {
                $condition = [
                    'trade_id' => $order->trade_id,
                    'original_no' => $order->original_no,
                    'paymode' => $order->paymode,
                    'pay_type' => $order->pay_type,
                    'currency' => $order->currency,
                    'pay' => $order->pay,
                    'balance' => TradeOrder::BALANCE_REFUND,
                ];
                if (TradeOrder::find()->where($condition)->exists()) {
                    continue;
                }
                $refundOrders[$order->paymode] = $condition;
            }
        }
        $transaction = Yii::$app->db->beginTransaction();
        try {
            if (!empty($refundOrders)) {
                foreach ($refundOrders as $paymode => $attributes) {
                    $rollbackOrder = new TradeOrder();
                    $rollbackOrder->attributes = $attributes;
                    $rollbackOrder->setMark('[' . $prefixMessage . ']系统自动取消交易订单');
                    if (!$rollbackOrder->save()) {
                        throw new Exception('退款交易订单申请创建失败！' . $rollbackOrder->getErrorMsg());
                    }
                    $credit = false;
                    if ($paymode == self::PAYMODE_CREDIT) {
                        $credit = $rollbackOrder->pay * 10;
                        //回滚账户积分
                        $account = $trade->buyer->account;
                        $account->credit += $credit;
                        $account->updated_at = date('Y-m-d H:i:s');
                        if (!$account->save()) {
                            throw new Exception('账户积分回滚失败！' . print_r($account->errors, true));
                        }
                        //创建回滚积分日志
                        $creditLog = new \common\models\original\UserAccountLogs();
                        $creditLog->attributes = [
                            'user_id' => $trade->user_id,
                            'type' => 'credit',
                            'amount' => $credit,
                            'current' => $account->credit,
                            'ip' => '127.0.0.1',
                            'mark' => '[' . $prefixMessage . ']系统自动取消订单:' . $trade->subject,
                            'detail' => 'trade_order',
                            'detail_id' => $rollbackOrder->id,
                        ];
                        if (!$creditLog->save()) {
                            throw new Exception('积分日志更新失败！' . print_r($creditLog->errors, true));
                        }
                        //回滚成功修改退还订单
                        $rollbackOrder->pay_time = time();
                        $rollbackOrder->status = TradeOrder::STATUS_SUCCESS;
                        $rollbackOrder->pay_no = (string) $creditLog->id;
                        if (!$rollbackOrder->save()) {
                            throw new Exception('退款积分通知保存时失败！' . print_r($rollbackOrder->errors, true));
                        }
                    }
                }
            }
            $tradeAmount = $trade->getOrders()->sum('pay*status*balance');
            if ($tradeAmount == 0) {
                $trade->setMark('[' . $prefixMessage . ']系统自动关闭当前交易');
                $trade->status = self::STATUS_CLOSED;
            } else {
                $trade->status = self::STATUS_CENCELED;
                $trade->setMark('[' . $prefixMessage . ']系统自动取消当前交易');
            }
            if (!$trade->save()) {
                throw new Exception('交易保存失败！' . $trade->getErrorMsg());
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $msg = $e->getMessage();
            return false;
        }
        return true;
    }

    /**
     * 查询当前外部订单号的交易支付状态
     * @param string $bizno
     * @return boolean
     */
    public static function resultByBizno($bizno) {
        $trades = static::find()
        ->where(['bizno' => $bizno])
        ->andWhere([
            'status' => [
                static::STATUS_SUCCESS,
                static::STATUS_FINISHED
            ]
        ])
        ->all();
        if (!empty($trades)) {
            return $trades[0]['return_url'];
            # return true;
        } else {
            return false;
        }
    }

}
